package main

import (
	"archive/zip"
	"bytes"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"os"
)

type Item struct {
	Href  string `xml:"href,attr"`
	ID    string `xml:"id,attr"`
	Media string `xml:"media-type,attr"`
	Props string `xml:"properties,attr,omitempty"`
}

type Manifest struct {
	Items []Item `xml:"item"`
}

type Package struct {
	XMLName  xml.Name `xml:"package"`
	Manifest Manifest `xml:"manifest"`
}

func extractCoverFromEpub(epubPath string) (*bytes.Buffer, error) {
	// 打开 ePub 文件（ZIP 文件）
	r, err := zip.OpenReader(epubPath)
	if err != nil {
		return nil, err
	}
	defer r.Close()

	var contentfile *zip.File
	var cover_href string = ""

	// 遍历 ePub 文件中的文件
	for _, f := range r.File {

		if f.Name == "OEBPS/content.opf" {
			contentfile = f
		}

		if f.Name == "cover.jpg" || f.Name == "cover.png" || f.Name == "cover.jpeg" || f.Name == "OEBPS/images/cover.jpg" || f.Name == "OEBPS/images/cover.png" || f.Name == "OEBPS/images/cover.jpeg" || f.Name == "META-INF/cover.jpg" || f.Name == "META-INF/cover.png" || f.Name == "META-INF/cover.jpeg" {
			rc, err := f.Open()
			if err != nil {
				return nil, err
			}
			defer rc.Close()

			var cover bytes.Buffer
			if _, err := io.Copy(&cover, rc); err != nil {
				return nil, err
			}
			return &cover, nil
		}
	}

	cc, err := contentfile.Open()
	if err != nil {
		fmt.Println("Error opening OPF file in zip:", err)
		return nil, err
	}
	defer cc.Close()

	// 读取OPF文件内容
	data, err := ioutil.ReadAll(cc)
	if err != nil {
		fmt.Println("Error reading OPF file content:", err)
		return nil, err
	}

	// 解析OPF文件
	var pkg Package
	err = xml.Unmarshal(data, &pkg)
	if err != nil {
		fmt.Println("Error unmarshalling XML:", err)
		return nil, err
	}

	// 遍历manifest中的items，寻找id为"cover-image"的item
	for _, item := range pkg.Manifest.Items {
		if item.ID == "cover-image" {
			// fmt.Println("Cover image href:", item.Href)
			// return nil, err
			cover_href = item.Href
		}
	}

	if cover_href != "" {
		// 遍历 ePub 文件中的文件
		for _, f := range r.File {

			if f.Name == "OEBPS/"+cover_href {
				rc, err := f.Open()
				if err != nil {
					return nil, err
				}
				defer rc.Close()

				var cover bytes.Buffer
				if _, err := io.Copy(&cover, rc); err != nil {
					return nil, err
				}
				return &cover, nil
			}

		}
	}
	return nil, nil
}

func main() {
	if len(os.Args) != 2 {
		fmt.Println("Usage: go run main.go <path_to_epub>")
		os.Exit(1)
	}

	epubPath := os.Args[1]
	coverImage, err := extractCoverFromEpub(epubPath)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	if coverImage == nil {
		fmt.Println("no cover image find")
		os.Exit(0)
	}

	// 将封面图像写入标准输出
	if _, err := io.Copy(os.Stdout, coverImage); err != nil {
		fmt.Println("Failed to write cover image to stdout:", err)
		os.Exit(1)
	}
}
